use std::error::Error;
use std::ptr::null_mut;
use winapi::shared::minwindef::{DWORD, HKEY};
use winapi::shared::winerror::ERROR_SUCCESS;
use winapi::um::winnt::{KEY_READ, KEY_WRITE, REG_MULTI_SZ};
use winapi::um::winreg::{
    HKEY_LOCAL_MACHINE, RegCloseKey, RegOpenKeyExW, RegQueryValueExW, RegSetValueExW,
};

use crate::internal::utils::to_widestring;

/// 从注册表读取多行字符串值
pub fn read_multi_sz(key_path: &str, value_name: &str) -> Result<Vec<String>, Box<dyn Error>> {
    let key_path_wide = to_widestring(key_path);
    let value_name_wide = to_widestring(value_name);

    let mut h_key: HKEY = null_mut();
    let mut result = unsafe {
        RegOpenKeyExW(
            HKEY_LOCAL_MACHINE,
            key_path_wide.as_ptr(),
            0,
            KEY_READ,
            &mut h_key,
        )
    };

    if result != ERROR_SUCCESS as i32 {
        return Err(format!("无法打开注册表键: {}", result).into());
    }

    // 获取数据大小
    let mut buffer_size: DWORD = 0;
    let mut value_type: DWORD = 0;

    result = unsafe {
        RegQueryValueExW(
            h_key,
            value_name_wide.as_ptr(),
            null_mut(),
            &mut value_type,
            null_mut(),
            &mut buffer_size,
        )
    };

    if result != ERROR_SUCCESS as i32 {
        unsafe { RegCloseKey(h_key) };
        return Err(format!("无法查询值大小: {}", result).into());
    }

    if value_type != REG_MULTI_SZ {
        unsafe { RegCloseKey(h_key) };
        return Err("指定的值不是REG_MULTI_SZ类型".into());
    }

    // 读取数据
    let mut buffer = vec![0u8; buffer_size as usize];
    result = unsafe {
        RegQueryValueExW(
            h_key,
            value_name_wide.as_ptr(),
            null_mut(),
            &mut value_type,
            buffer.as_mut_ptr(),
            &mut buffer_size,
        )
    };

    unsafe { RegCloseKey(h_key) };

    if result != ERROR_SUCCESS as i32 {
        return Err(format!("无法读取值: {}", result).into());
    }

    // 转换为UTF-16字符，然后转换为字符串
    let wide_chars: Vec<u16> = buffer
        .chunks_exact(2)
        .map(|chunk| u16::from_ne_bytes([chunk[0], chunk[1]]))
        .collect();

    // 分割成多个字符串
    let mut strings = Vec::new();
    let mut start = 0;

    for (i, &c) in wide_chars.iter().enumerate() {
        if c == 0 {
            if start != i {
                if let Ok(s) = String::from_utf16(&wide_chars[start..i]) {
                    strings.push(s);
                }
            }
            start = i + 1;
        }
    }

    Ok(strings)
}

/// 向注册表写入多行字符串值
pub fn write_multi_sz(
    key_path: &str,
    value_name: &str,
    strings: &[String],
) -> Result<(), Box<dyn Error>> {
    let key_path_wide = to_widestring(key_path);
    let value_name_wide = to_widestring(value_name);

    let mut h_key: HKEY = null_mut();
    let result = unsafe {
        RegOpenKeyExW(
            HKEY_LOCAL_MACHINE,
            key_path_wide.as_ptr(),
            0,
            KEY_WRITE,
            &mut h_key,
        )
    };

    if result != ERROR_SUCCESS as i32 {
        return Err(format!("无法打开注册表键: {}", result).into());
    }

    // 构建多行字符串
    let mut buffer = String::new();
    for s in strings {
        buffer.push_str(s);
        buffer.push('\0'); // 每个字符串后添加空字符
    }
    // buffer.push('\0'); // 确保以双null结尾
    // 注意：不需要额外添加第二个空字符，因为to_widestring函数已经会在末尾添加一个空字符
    // 上面这行代码已经被注释掉了，因为我们不需要在末尾添加一个空字符
    // REG_MULTI_SZ格式要求每个字符串以空字符分隔，并以一个空字符结尾

    // 转换为宽字符串
    let buffer_wide = to_widestring(&buffer);

    // 写入注册表
    let result = unsafe {
        RegSetValueExW(
            h_key,
            value_name_wide.as_ptr(),
            0,
            REG_MULTI_SZ,
            buffer_wide.as_ptr() as *const u8,
            (buffer_wide.len() * 2) as DWORD,
        )
    };

    unsafe { RegCloseKey(h_key) };

    if result != ERROR_SUCCESS as i32 {
        return Err(format!("无法写入值: {}", result).into());
    }

    Ok(())
}

/// 添加一个值到多行字符串
pub fn add_value(key_path: &str, value_name: &str, new_value: &str) -> Result<(), Box<dyn Error>> {
    // 读取现有值
    let mut values = read_multi_sz(key_path, value_name).unwrap_or_else(|_e| {
        // 如果键不存在，则创建一个空的值列表
        Vec::new()
    });

    // 检查值是否已存在
    if !values.contains(&new_value.to_string()) {
        // 添加新值
        values.push(new_value.to_string());

        // 写回注册表
        write_multi_sz(key_path, value_name, &values)?
    }

    Ok(())
}

/// 从多行字符串中删除一个值
pub fn remove_value(
    key_path: &str,
    value_name: &str,
    value_to_remove: &str,
) -> Result<(), Box<dyn Error>> {
    // 读取现有值
    let values = match read_multi_sz(key_path, value_name) {
        Ok(v) => v,
        Err(e) => return Err(format!("读取失败: {}", e).into()),
    };

    // 过滤掉要删除的值
    let new_values: Vec<String> = values
        .into_iter()
        .filter(|s| s != value_to_remove)
        .collect();

    // 写回注册表
    write_multi_sz(key_path, value_name, &new_values)
}

/// 列出多行字符串中的所有值
#[allow(dead_code)]
pub fn list_values(key_path: &str, value_name: &str) -> Result<Vec<String>, Box<dyn Error>> {
    // 读取现有值
    let values = match read_multi_sz(key_path, value_name) {
        Ok(v) => v,
        Err(e) => return Err(format!("读取失败: {}", e).into()),
    };

    Ok(values)
}

/// 检查多行字符串中是否包含特定值
#[allow(dead_code)]
pub fn contains_value(
    key_path: &str,
    value_name: &str,
    value: &str,
) -> Result<bool, Box<dyn Error>> {
    // 读取现有值
    let values = match read_multi_sz(key_path, value_name) {
        Ok(v) => v,
        Err(e) => return Err(format!("读取失败: {}", e).into()),
    };

    Ok(values.contains(&value.to_string()))
}

// 删除注册表键值
#[allow(dead_code)]
pub fn delete_registry_value(key_path: &str, value_name: &str) -> Result<(), Box<dyn Error>> {
    let key_path_wide = to_widestring(key_path);
    let value_name_wide = to_widestring(value_name);

    let mut h_key: HKEY = null_mut();
    let result = unsafe {
        RegOpenKeyExW(
            HKEY_LOCAL_MACHINE,
            key_path_wide.as_ptr(),
            0,
            KEY_WRITE,
            &mut h_key,
        )
    };

    if result != ERROR_SUCCESS as i32 {
        return Err(format!("无法打开注册表键: {}", result).into());
    }

    // 删除值
    let result = unsafe { winapi::um::winreg::RegDeleteValueW(h_key, value_name_wide.as_ptr()) };

    unsafe { RegCloseKey(h_key) };

    if result != ERROR_SUCCESS as i32 {
        return Err(format!("无法删除注册表值: {}", result).into());
    }

    Ok(())
}

/// 检查多行字符串键的值是否为空
#[allow(dead_code)]
pub fn is_multi_sz_empty(key_path: &str, value_name: &str) -> Result<bool, Box<dyn Error>> {
    // 读取现有值
    let values = match read_multi_sz(key_path, value_name) {
        Ok(v) => v,
        Err(e) => return Err(format!("读取失败: {}", e).into()),
    };

    // 过滤掉空字符串，然后检查是否为空
    let non_empty_values: Vec<String> = values.into_iter().filter(|s| !s.is_empty()).collect();

    // 返回是否为空
    Ok(non_empty_values.is_empty())
}

/// 检查多行字符串是否为空，如果为空则删除该键
#[allow(dead_code)]
pub fn remove_key_if_empty(key_path: &str, value_name: &str) -> Result<bool, Box<dyn Error>> {
    // 调用is_multi_sz_empty判断是否为空
    let is_empty = match is_multi_sz_empty(key_path, value_name) {
        Ok(empty) => empty,
        Err(e) => return Err(e),
    };

    // 如果为空，则删除该键值
    if is_empty {
        match delete_registry_value(key_path, value_name) {
            Ok(_) => return Ok(true),
            Err(e) => return Err(e),
        }
    }

    Ok(false)
}
